/**
 * All Rights Reserved , Copyright (C) 2020 , 青岛鼎信通讯股份有限公司
 * <p>
 * MeetPersonRecordService
 * 会议人员记录
 * <p>
 * 修改纪录
 * 2020-10-31 版本：1.0 donghang 创建。
 *
 * @version 版本：1.0
 * @author 作者：donghang
 * 创建日期：2020-10-31
 */
package com.topscomm.meet.service.impl;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import cn.hutool.core.util.StrUtil;
import com.topscomm.base.BaseSystemConst;
import com.topscomm.mpm.service.IMpmProjectStakeholderService;
import com.topscomm.tap.common.DatacodeCache;
import com.topscomm.tap.lock.ZookeeperDistributeLock;
import com.topscomm.work.WorkSystemConst;
import com.topscomm.work.pojo.WorkScheduleEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.remoting.RemoteAccessException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.topscomm.base.BaseSystemConst.BaseOperateTypeEnum;
import com.topscomm.base.BaseSystemConst.ShareTypeEnum;
import com.topscomm.base.pojo.BaseOperateRecordEntity;
import com.topscomm.base.pojo.BasePermissionManageEntity;
import com.topscomm.base.service.IBaseCboUserExtendService;
import com.topscomm.base.service.IBaseOperateRecordService;
import com.topscomm.base.service.IBasePermissionManageService;
import com.topscomm.base.service.IBaseRemindConfigService;
import com.topscomm.basic.BasicEntity;
import com.topscomm.basic.exception.ServiceException;
import com.topscomm.cbo.pojo.CboUserEntity;
import com.topscomm.meet.MeetSystemConst.MeetInviteMode;
import com.topscomm.meet.MeetSystemConst.MeetOperateTypeEnum;
import com.topscomm.meet.MeetSystemConst.MeetPersonType;
import com.topscomm.meet.MeetSystemConst.MeetPersonTypeEnum;
import com.topscomm.meet.MeetSystemConst.MeetSignStateEnum;
import com.topscomm.meet.MeetSystemConst.MeetStateEnum;
import com.topscomm.meet.MeetSystemConst.MeetSubmitStateEnum;
import com.topscomm.meet.pojo.MeetManageEntity;
import com.topscomm.meet.pojo.MeetPersonRecordEntity;
import com.topscomm.meet.service.IMeetManageService;
import com.topscomm.meet.service.IMeetPersonRecordService;
import com.topscomm.meet.service.impl.auto.MeetPersonRecordServiceAuto;
import com.topscomm.pub.util.ConvertUtil;
import com.topscomm.pub.util.StringBufferProxy;
import com.topscomm.pub.util.StringUtil;
import com.topscomm.tap.common.ParameterCache;
import com.topscomm.tap.common.SessionUserBean;

import static com.topscomm.meet.MeetSystemConst.MeetSourceAppEnum.MPM;

@Slf4j
@Service(value = "meetPersonRecordService")
@Scope(value = "singleton")
public class MeetPersonRecordService extends MeetPersonRecordServiceAuto implements IMeetPersonRecordService {
    @Autowired
    IBaseOperateRecordService baseOperateRecordService;
    @Autowired
    IBaseCboUserExtendService baseCboUserExtendService;
    @Autowired
    IBasePermissionManageService basePermissionManageService;
    @Autowired
    IBaseRemindConfigService baseRemindConfigService;
    @Autowired
    IMeetManageService meetManageService;
    @Autowired
    IMpmProjectStakeholderService mpmProjectStakeholderService;
    @Autowired
    ZookeeperDistributeLock lock;

    /**
     * 查询会议的相关人员,包括已回执、未回执、签到、未签到
     *
     * @param meetId
     * @param operateState
     * @return
     * @description:
     * @author: donghang
     * @date: 2020年10月31日下午5:27:22
     * @modify:
     */
    @Override
    public List<Map<String, Object>> queryUserRecord(String meetId, String operateState) {
        // 查询已签到的人员
        if (StringUtil.isEmpty(meetId)) {
            return new ArrayList<>();
        }
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" 1=1 ");
        if (MeetOperateTypeEnum.YesSign.equals(operateState)) {
            sql.appendSingle(" and meetid='{0}' and signstate={1}", meetId, MeetSignStateEnum.Signed);
        } else if (MeetOperateTypeEnum.NoSign.equals(operateState)) {
            sql.appendSingle(" and meetid='{0}' and signstate={1}", meetId, MeetSignStateEnum.NoSign);
        } else if (MeetOperateTypeEnum.YesAttendSubmit.equals(operateState)) {
            sql.appendSingle(" and meetid='{0}' and submitstate={1}", meetId, MeetSubmitStateEnum.AttendSubmit);
        } else if (MeetOperateTypeEnum.NoAttendSubmit.equals(operateState)) {
            sql.appendSingle(" and meetid='{0}' and submitstate={1}", meetId, MeetSubmitStateEnum.NoSubmit);
        }
        return this.queryMapByWhere(sql.toString());
    }

    /**
     * @param meetid
     * @param userList
     * @description: 插入发起人配置的会议人员记录
     * @author: wanghongwei
     * @date: 2020-11-5 15:47:10
     * @modify:
     */
    @Override
    public void insertDataList(String meetid, List<Map<String, Object>> userList) {
        if (userList.isEmpty()) {
            return;
        }
        List<BasicEntity> listEntity = new ArrayList<>();
        for (Map<String, Object> userMap : userList) {
            MeetPersonRecordEntity entity = MeetPersonRecordEntity.builder().build();
            entity.setMeetid(meetid);
            entity.setOrgcode(ConvertUtil.convertToString(userMap.get(MeetPersonRecordEntity.FieldOrgcode)));
            entity.setDeptcode(ConvertUtil.convertToString(userMap.get(MeetPersonRecordEntity.FieldDeptcode)));
            entity.setUsercode(ConvertUtil.convertToString(userMap.get(CboUserEntity.FieldCode)));
            entity.setUsername(ConvertUtil.convertToString(userMap.get(CboUserEntity.FieldName)));
            entity.setInviteusercode(getSessionUserBean().getUser().getCode());
            entity.setInviteusername(getSessionUserBean().getUser().getName());
            entity.setInvitetype(MeetInviteMode.Configure);
            entity.setPersontype(MeetPersonType.Attend);
            listEntity.add(entity);
        }
        //在插入前 与其他项目联动 进行一些远程调用
        beforeInsertPersonRecordList(meetid, "", listEntity);
        if (listEntity.size() > 0) {
            this.insertBatch(listEntity);
        }
    }


    /**
     * @param sessionUserBean
     * @param meetid
     * @description: 签到
     * @author: wanghongwei
     * @date: 2020-11-5 10:14:14
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void sign(String meetid, String replaceusercode, String replaceusername) {
        Map<String, Object> updateMap = new HashMap<>();
        //判断人员能否进行签到
        StringBuilder errorMessage = new StringBuilder();
        boolean isCanSign = isCanSign(meetid, replaceusercode, errorMessage);
        if (isCanSign) {
            //进行签到 只在update中用到
            updateMap.put(MeetPersonRecordEntity.FieldSignstate, MeetSignStateEnum.Signed);
            updateMap.put(MeetPersonRecordEntity.FieldSigndate, new Date());
            //获取参会人员记录
            SessionUserBean sessionUserBean = this.getSessionUserBean();
            String usercode = StrUtil.isEmpty(replaceusercode) ? sessionUserBean.getUser().getCode() : replaceusercode;
            String username = StrUtil.isEmpty(replaceusername) ? sessionUserBean.getUser().getName() : replaceusername;
            List<Map<String, Object>> personRecordList = this.searchPersonRecordList(meetid, usercode);
            if (personRecordList.size() > 0) {
                //获取人员记录 塞到map中进行更新
                updateMap.putAll(personRecordList.get(0));
            } else {
                //没有参会记录 无法签到
                throw new ServiceException("您不属于参会人员，无需签到！");
            }
            updateMap.put(MeetPersonRecordEntity.FieldUsercode, usercode);
            //进行签到
            this.update(updateMap);
            //添加签到的操作记录
            String operateResult = StrUtil.isEmpty(replaceusercode) ? username + "签到成功" : username + "替" + replaceusername + "签到成功";
            this.baseOperateRecordService
                    .insert(this.getBaseOperatorRecordEntity(meetid, sessionUserBean, BaseOperateTypeEnum.Sign, operateResult));
        } else {
            //不能签到
            throw new ServiceException(errorMessage.toString());
        }
    }

    /**
     * @param sessionUserBean
     * @param meetid
     * @param usercode
     * @param username
     * @description: 指派人员参会
     * @author: wanghongwei
     * @date: 2020-11-5 15:29:57
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String assign(String meetid, String usercode, String username) {
        SessionUserBean sessionUserBean = this.getSessionUserBean();
        String loginUsercode = sessionUserBean.getUser().getCode();
        //指派他人 则自己无需签到 修改自己的签到类型
        this.updateSignState(meetid, loginUsercode);
        Map<String, Object> dataMap = new HashMap<>();
        String operateResult = sessionUserBean.getUser().getName() + "指派" + username + "替代参会";
        return this.operate(sessionUserBean, meetid, usercode, username, BaseOperateTypeEnum.Assign, operateResult);
    }

    /**
     * 删除会议当前人所指派的所有人
     * @author xinfushuo
     * @param
     * @throws
     * @return
     * @date 2023/3/24
     * @modify
     */
    @Override
    public void deleteByAssignUser(String meetid, SessionUserBean userBean, String usercode, String username) {
        //从参会人员记录中删除
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("meetid = '{0}' and {1}='{2}' and {3}='{4}' "
                , meetid, MeetPersonRecordEntity.FieldInviteusercode, userBean.getUser().getCode(), MeetPersonRecordEntity.FieldInvitetype, MeetInviteMode.Assign);
        List<MeetPersonRecordEntity> persons = this.queryByWhere(sql.toString());
        this.deleteByWhere(sql.toString());
        //更新basePermisson表
        List<BasePermissionManageEntity> entities = getUserPermissonList(meetid);
        if (!entities.isEmpty()) {
            //删除shareObject中的人员
            entities.forEach(entity -> persons.forEach(person -> {
                entity.setShareobjects(removeFromString(entity.getShareobjects(), person.getUsercode()));
                entity.setShareobjectsdesc(removeFromString(entity.getShareobjectsdesc(), person.getUsername()));
            }));
        }
        this.basePermissionManageService.updateBatchMap(entities.stream().map(this::convertToMap).collect(Collectors.toList()));
    }

    private String removeFromString(String StringList, String item) {
        return Arrays.stream(StringList.split(",")).filter(code -> !item.equals(code)).collect(Collectors.joining(","));
    }

    /**
     * @param meetid
     * @param usercode
     * @param username
     * @description: 邀请人员参会
     * @author: wanghongwei
     * @date: 2020-11-5 15:30:28
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public String invite(String meetid, String usercode, String username) {
        beforeInvite(meetid, usercode, username);
        SessionUserBean sessionUserBean = this.getSessionUserBean();
        String operateResult = sessionUserBean.getUser().getName() + "邀请" + username + "参会";
        return this.operate(sessionUserBean, meetid, usercode, username, BaseOperateTypeEnum.Invite, operateResult);
    }

    /**
     * 邀请他人参加本会之前检测条件
     * 1.邀请人即当前人需要是参会人
     *
     * @param
     * @return
     * @throws
     * @author xinfushuo
     * @date 2022/8/31
     * @modify
     */
    private void beforeInvite(String meetid, String usercode, String username) {
        MeetManageEntity meetManageEntity = meetManageService.queryById(meetid);
        List<Map<String, Object>> personRecordList = this.searchPersonRecordList(meetid, this.getSessionUserBean().getUser().getCode());
        if (personRecordList.isEmpty()) {
            throw new ServiceException("您尚未参会，无法邀请其他人加入该会议。");
        }
    }

    /**
     * @param dataMap
     * @param sessionUserBean
     * @description: 报名参会
     * @author: wanghongwei
     * @date: 2020-11-5 15:30:09
     * @modify:
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void join(Map<String, Object> dataMap) {
        //获取当前用户code name 进行operate
        SessionUserBean sessionUserBean = this.getSessionUserBean();
        dataMap.put(MeetPersonRecordEntity.FieldUsercode, sessionUserBean.getUser().getCode());
        dataMap.put(MeetPersonRecordEntity.FieldUsername, sessionUserBean.getUser().getName());
        String meetid = ConvertUtil.convertToString(dataMap.get(MeetPersonRecordEntity.FieldMeetid));
        MeetManageEntity meetEntity = meetManageService.queryById(meetid);
        String usercode = ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldUsercode));
        String username = ConvertUtil.convertToString(dataMap.get(MeetManageEntity.FieldUsername));
        String lockPath = "meet_join_" + meetid;
        try {
            lock.getLock(lockPath);
            beforeJoin(meetid, usercode, meetEntity);
            //最终使用meetid进行参会
            String operateResult = username + "报名参会！";
            //参会 并添加参会操作记录 对接工作日程
            joinMeet(meetid, usercode, username, null, null, BaseOperateTypeEnum.Join, operateResult, this.getSessionUserBean());
            afterJoin(meetid, usercode, meetEntity);
        } finally {
            lock.releaseLock(lockPath);
        }
    }

    /**
     * 参会前进行校验
     *
     * @param
     * @return
     * @throws
     * @author xinfushuo
     * @date 2022/9/1
     * @modify
     */
    private void beforeJoin(String meetid, String usercode, MeetManageEntity entity) {
        //若会议未发布
        if (MeetStateEnum.Publish != entity.getState()) {
            throw new ServiceException("该会议未处于发布状态！");
        }
        //若会议已停止签到
        if (entity.getSignstate() == BaseSystemConst.CboYesNoEnum.No) {
            throw new ServiceException("该会议已停止签到，无法参会!");
        }
        List<Map<String, Object>> joinRecords = this.searchPersonRecordList(meetid, usercode);
        if (!joinRecords.isEmpty()) {
            throw new ServiceException("您已参会，无需重复参会。");
        }
    }

    /**
     * 参会后进行操作 如销售项目来源会议直接进行签到
     *
     * @param
     * @return
     * @throws
     * @author xinfushuo
     * @date 2022/9/1
     * @modify
     */
    private void afterJoin(String meetid, String usercode, MeetManageEntity entity) {
        //对于特殊来源会议 参会可以直接签到
        try {
            this.sign(meetid, "", "");
        } catch (ServiceException e) {
            log.info("meetid:" + entity.getId() + " usercode:" + getSessionUserBean().getUser().getCode() + e.getMessage());
        }
    }


    /**
     * @param dataMap
     * @return
     * @description: 得到参会人员统计数字
     * @author: wanghongwei
     * @date: 2020-11-25 9:16:59
     * @modify:
     */
    @Override
    public Map<String, Object> getPersonStaticCount(Map<String, Object> dataMap) {
        Map<String, Object> staticMap = new HashMap<>();
        String meetId = ConvertUtil.convertToString(dataMap.get(MeetPersonRecordEntity.FieldMeetid));
        staticMap.put("noSubmitCount",
                this.getQueryCount(meetId, MeetPersonRecordEntity.FieldSubmitstate, MeetSubmitStateEnum.NoSubmit));
        staticMap.put("attendCount",
                this.getQueryCount(meetId, MeetPersonRecordEntity.FieldSubmitstate, MeetSubmitStateEnum.AttendSubmit));
        staticMap.put("noAttendCount", this.getQueryCount(meetId, MeetPersonRecordEntity.FieldSubmitstate,
                MeetSubmitStateEnum.NoAttendSubmit));
        staticMap.put("signCount",
                this.getQueryCount(meetId, MeetPersonRecordEntity.FieldSignstate, MeetSignStateEnum.Signed));
        staticMap.put("noSignCount",
                this.getQueryCount(meetId, MeetPersonRecordEntity.FieldSignstate, MeetSignStateEnum.NoSign));
        staticMap.put("noNeedSignCount",
                this.getQueryCount(meetId, MeetPersonRecordEntity.FieldSignstate, MeetSignStateEnum.NoNeedSign));
        return staticMap;
    }

    /**
     * @param usercode
     * @param meetid
     * @param inviteusercode
     * @param inviteusername
     * @param inviteMode     = operatetype
     * @description: 插入指派、邀请、报名参加的会议人员记录
     * @author: wanghongwei
     * @date: 2020-11-5 16:07:54
     * @modify:
     */
    @Transactional(rollbackFor = Exception.class)
    public void insertDataList(String meetid, String usercodes, String inviteusercode, String inviteusername, String inviteMode) {
        //获取用户名 会议id 邀请人姓名 邀请人code 来插入会议人员记录
        List<Map<String, Object>> userList = this.baseCboUserExtendService.searchUsersByUserCodes(usercodes);
        List<BasicEntity> listEntity = new ArrayList<>();
        for (Map<String, Object> userMap : userList) {
            MeetPersonRecordEntity entity = MeetPersonRecordEntity.builder().build();
            entity.setMeetid(meetid);
            entity.setOrgcode(ConvertUtil.convertToString(userMap.get(MeetPersonRecordEntity.FieldOrgcode)));
            entity.setDeptcode(ConvertUtil.convertToString(userMap.get(MeetPersonRecordEntity.FieldDeptcode)));
            entity.setUsercode(ConvertUtil.convertToString(userMap.get(CboUserEntity.FieldCode)));
            entity.setUsername(ConvertUtil.convertToString(userMap.get(CboUserEntity.FieldName)));
            entity.setInviteusercode(inviteusercode);
            entity.setInviteusername(inviteusername);
            entity.setInvitetype(inviteMode);
            entity.setSignstate(MeetSignStateEnum.NoSign);
            entity.setPersontype(MeetPersonType.Attend);
            listEntity.add(entity);
        }
        beforeInsertPersonRecordList(meetid, inviteMode, listEntity);
        if (listEntity.size() > 0) {
            this.insertBatch(listEntity);
        }
    }

    private void beforeInsertPersonRecordList(String meetid, String inviteMode, List<BasicEntity> personRecords) {
        MeetManageEntity meetManageEntity = this.meetManageService.queryById(meetid);
        //指派人员直接进行参会
        if (BaseOperateTypeEnum.Assign.contentEquals(inviteMode)) {
            personRecords.forEach(basicEntity -> {
                ((MeetPersonRecordEntity) basicEntity).setSubmitstate(MeetSubmitStateEnum.AttendSubmit);
                ((MeetPersonRecordEntity) basicEntity).setSubmitdate(new Date());
            });
        }
        //会议管理人员及创建人员直接参会
        personRecords.forEach(basicEntity -> {
            MeetPersonRecordEntity person = (MeetPersonRecordEntity) basicEntity;
            boolean creater = person.getUsercode().contentEquals(meetManageEntity.getUsercode());
            String meetmanager = ConvertUtil.convertToString(meetManageEntity.getManageusercodes());
            boolean isManager = !meetmanager.isEmpty() && Arrays.stream(meetmanager.split(",")).anyMatch(code -> person.getUsercode().contentEquals(code));
            if (creater || isManager) {
                person.setSubmitstate(MeetSubmitStateEnum.AttendSubmit);
                person.setSubmitdate(new Date());
            }
        });
        List<String> usercodes =
                personRecords.stream().map(e -> (MeetPersonRecordEntity) e).map(MeetPersonRecordEntity::getUsercode).collect(Collectors.toList());
        //若为销售项目关联会议
        try {
            if (meetManageEntity.getSourceapp() != null && MPM.equals(meetManageEntity.getSourceapp())) {
                //获取相关方权限
                List<Map<String, Object>> StakeHolderList = mpmProjectStakeholderService.queryStakeholderMeet(meetManageEntity.getSourceid(), usercodes);
                Map<String, Map<String, Object>> userRoleMap = StakeHolderList.stream().map(m -> {
                    Map<String, Object> map = new HashMap<>();
                    map.put("usercode", ConvertUtil.convertToString(m.get("usercode")));
                    //角色展示值
                    map.put("role", ConvertUtil.convertToString(m.get("message")) + "/" + ConvertUtil.convertToString(m.get("grouprole")));
                    return map;
                }).collect(Collectors.toMap(s -> ConvertUtil.convertToString(s.get("usercode")), s -> s));
                //为参会人员赋值角色
                for (BasicEntity entity : personRecords) {
                    MeetPersonRecordEntity personRecordEntity = (MeetPersonRecordEntity) entity;
                    Map<String, Object> role = userRoleMap.get(personRecordEntity.getUsercode());
                    //不是所有参会人都有对应角色
                    if (role != null && !role.isEmpty()) {
                        personRecordEntity.setRolename(ConvertUtil.convertToString(role.get("role")));
                    }
                }
            }
            //捕获远程调用 超时等Exception
        } catch (RemoteAccessException remoteAccessException) {
            remoteAccessException.printStackTrace();
            log.warn(remoteAccessException.getMessage());
        }
    }

    /**
     * 参加会议 添加操作记录 添加日程
     *
     * @param
     * @return
     * @throws
     * @author xinfushuo
     * @date 2022/9/1
     * @modify
     */
    public void joinMeet(String meetid, String usercodes, String usernames, String invitecode, String invitename, String operateType, String operateResult, SessionUserBean userBean) {
        //插入参会人员记录
        this.insertDataList(meetid, usercodes, invitecode, invitename, operateType);
        //参入参会操作纪录
        this.baseOperateRecordService.insert(this.getBaseOperatorRecordEntity(meetid, userBean, operateType, operateResult));
        //关联工作日程
        this.addWorkSchedule(meetid, usercodes, usernames, userBean);
    }

    /**
     * @param usercode       单个多个用户code
     * @param inviteusercode 邀请用户工号
     * @param inviteusername 邀请用户姓名
     * @param userBean
     * @param meetid         会议id
     * @param usercodes
     * @param usernames
     * @param operateType
     * @return
     * @description: 指派、邀请和报名参加的操作（包括处理人员记录表和操作记录表、对接日程等）
     * @author: wanghongwei
     * @date: 2020-11-6 14:09:59
     * @modify:
     */
    private String operate(SessionUserBean userBean, String meetid, String usercodes, String usernames, String operateType, String operateResult) {
        List<Map<String, Object>> personRecordList = this.searchPersonRecordList(meetid, usercodes);
        StringBufferProxy message = new StringBufferProxy();
        //若根据会议id 以及 用户名 没有找到对应会议参会人 则进行参会
        //多次重复参会 或者 进行指派或邀请其他人参会
        //多人时 对未参会的进行参会
        this.addNoAttendPerson(personRecordList, meetid, usercodes, usernames, userBean, operateType, operateResult);
        String currentUserCode = this.getSessionUserBean().getUser().getCode();
        //对重复人员进行提示。
        for (Map<String, Object> map : personRecordList) {
            if (currentUserCode
                    .equals(ConvertUtil.convertToString(map.get(MeetPersonRecordEntity.FieldUsercode)))) {
                message.appendSingle("您" + ",");
            } else {
                message.appendSingle(
                        ConvertUtil.convertToString(map.get(MeetPersonRecordEntity.FieldUsername)) + ",");
            }
        }
        if (message.length() > 0) {
            message = message.substring(0, message.length() - 1);
            message.appendSingle("已经加入会议！");
        }
        return message.toString();
    }

    private void beforeOperate(Map<String, Object> paraMap) {

    }

    /**
     * @param personRecordList
     * @param dataMap
     * @param userBean
     * @param operateType
     * @description: 添加未参会人员
     * @author: wanghongwe
     * @date: 2020-11-25 14:23:06
     * @modify:
     */
    private void addNoAttendPerson(List<Map<String, Object>> personRecordList, String meetid, String usercodes, String usernames,
                                   SessionUserBean userBean, String operateType, String operateResult) {
        List<String> attendusercode = personRecordList.stream()
                .map(map -> ConvertUtil.convertToString(map.get(MeetPersonRecordEntity.FieldUsercode))).distinct()
                .collect(Collectors.toList());
        String[] usercodeArray = usercodes.split(",");
        String[] usernameArray = usernames.split(",");
        List<String> noAttendUsercode = new ArrayList<>();
        List<String> noAttendUsername = new ArrayList<>();
        for (int i = 0; i < usercodeArray.length; i++) {
            if (!attendusercode.contains(usercodeArray[i])) {
                noAttendUsercode.add(usercodeArray[i]);
                noAttendUsername.add(usernameArray[i]);
            }
        }
        //若peronalRecordList不包含usercode 中的人，则对不包括的进行参会
        if (noAttendUsercode.size() > 0) {
            usercodes = String.join(",", noAttendUsercode);
            usernames = String.join(",", noAttendUsername);
            this.insertDataList(meetid, usercodes, this.getSessionUserBean().getUser().getCode(), this.getSessionUserBean().getUser().getName(), operateType);
            this.baseOperateRecordService.insert(this.getBaseOperatorRecordEntity(meetid, userBean, operateType, operateResult));
            this.addWorkSchedule(meetid, usercodes, usernames, userBean);
        }
    }

    /**
     * @param dataMap
     * @param userBean
     * @description: 未参会人员对接日程
     * @author: wanghongwei
     * @date: 2020-11-25 15:30:54
     * @modify:
     */
    private void addWorkSchedule(String meetid, String usercode, String username, SessionUserBean userBean) {
        List<BasePermissionManageEntity> permissionList = this.getPermissionList(meetid, usercode, username, userBean);
        // 保存会议权限信息
        this.basePermissionManageService.batchSaveList(meetid, MeetManageEntity.tableName, permissionList);
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" 1=1 ");
        sql.appendSingle(" and sourceid = '{0}'", meetid);
        sql.appendSingle(" and sourcetype = '{0}'", MeetManageEntity.tableName);
        List<Map<String, Object>> remindList = this.baseRemindConfigService.queryMapByWhere(sql.toString());
        // 更新提醒信息，为了提示日程消息需要发送
        this.baseRemindConfigService.updateBatchMap(remindList);
        // 对接日程信息
        MeetManageEntity meetManageEntity = this.meetManageService.queryById(meetid);
        this.meetManageService.submitWorkSchedule(meetManageEntity, remindList, permissionList, true, false);
    }

    /**
     * @param meetId
     * @param dataMap
     * @param userBean
     * @return
     * @description: 获取基础权限列表
     * @author: wanghongwei
     * @date: 2020-11-25 17:37:38
     * @modify:
     */
    private List<BasePermissionManageEntity> getPermissionList(String meetId, String usercode, String username,
                                                               SessionUserBean userBean) {
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" 1=1 ");
        sql.appendSingle(" and sourcetype = '{0}'", MeetManageEntity.tableName);
        sql.appendSingle(" and sourceid = '{0}'", meetId);
        List<BasePermissionManageEntity> permissionList = this.basePermissionManageService.queryByWhere(sql.toString());
        BasePermissionManageEntity basePermissionEntity = null;
        if (permissionList.size() > 0) {
            for (BasePermissionManageEntity entity : permissionList) {
                if (Objects.equals(entity.getSharetype(), ShareTypeEnum.User)) {
                    basePermissionEntity = entity;
                    break;
                }
            }
        }
        if (basePermissionEntity != null) {
            basePermissionEntity.setShareobjects(basePermissionEntity.getShareobjects() + "," + usercode);
            basePermissionEntity.setShareobjectsdesc(basePermissionEntity.getShareobjectsdesc() + "," + username);
        } else {
            Map<String, Object> users = new HashMap<>();
            users.put("usercodes", usercode);
            users.put("usernames", username);
            List<BasePermissionManageEntity> newPermissionList = this.basePermissionManageService.processSelectUsers(
                    users, MeetPersonTypeEnum.Attend, userBean.getUser().getCode(), userBean.getUser().getName());
            permissionList.addAll(newPermissionList);
        }
        return permissionList;
    }

    /**
     * 获取基础权限配置表
     * @author xinfushuo
     * @param
     * @throws
     * @return
     * @date 2023/3/23
     * @modify
     */
    public List<BasePermissionManageEntity> getUserPermissonList(String meetid) {
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("(SOURCETYPE  = '{0}' AND SOURCEID  = '{1}') OR  (SOURCETYPE = '{2}' AND SOURCEID = (SELECT id FROM WORKSCHEDULE w WHERE w.SOURCETYPE = '{3}' AND w.SOURCEID  = '{4}'))", MeetManageEntity.tableName, meetid, WorkSystemConst.WorkSourceTypeEnum.WorkSchedule, MeetManageEntity.tableName, meetid);
        return this.basePermissionManageService.queryByWhere(sql.toString()).stream().filter(basePermissionManageEntity -> Objects.equals(basePermissionManageEntity.getSharetype(), ShareTypeEnum.User)).collect(Collectors.toList());
    }

    /**
     * @param meetid
     * @param usercode 单个或多个用户 多个以逗号隔开。
     * @return
     * @description: 查询已经参会的会议人员记录(id和username)
     * @author: wanghongwei
     * @date: 2020-11-6 10:01:39
     * @modify:
     */
    private List<Map<String, Object>> searchPersonRecordList(String meetid, String usercodes) {
        List<Map<String, Object>> userMapList = new ArrayList<>();
        if (!StrUtil.isEmpty(usercodes)) {
            String codeParam = new ArrayList<>(Arrays.asList(usercodes.split(","))).stream().map(s -> "'" + s + "'").collect(Collectors.joining(","));
            StringBufferProxy sql = new StringBufferProxy();
            sql.appendSingle(" 1=1 ");
            sql.appendSingle(" and meetid = '{0}'", meetid);
            sql.appendSingle(" and usercode in ({0})", codeParam);
            List<String> fieldList = Arrays.asList(MeetPersonRecordEntity.FieldId, MeetPersonRecordEntity.FieldUsercode,
                    MeetPersonRecordEntity.FieldUsername);
            userMapList = this.queryMapFieldsByWhere(sql.toString(), fieldList);
        }
        return userMapList;
    }

    /**
     * @param dataMap
     * @param userBean
     * @param operateType
     * @return
     * @description: 得到操作记录类实体
     * @author: wanghongwei
     * @date: 2020-11-5 16:58:51
     * @modify:
     */
    private BaseOperateRecordEntity getBaseOperatorRecordEntity(String meetid, SessionUserBean userBean,
                                                                String operateType, String operateResult) {
        BaseOperateRecordEntity entity = getBasicEntity(meetid, userBean);
        entity.setOperatetype(operateType);
        entity.setOperateresult(operateResult);
        return entity;
    }

    /**
     * @param
     * @return
     * @throws
     * @author xinfushuo
     * @date 2022/9/1
     * @modify
     */
    private BaseOperateRecordEntity getBasicEntity(String meetid, SessionUserBean userBean) {
        BaseOperateRecordEntity entity = new BaseOperateRecordEntity();
        entity.setOrgcode(userBean.getOrg().getCode());
        entity.setDeptcode(userBean.getDept().getCode());
        entity.setUsercode(userBean.getUser().getCode());
        entity.setUsername(userBean.getUser().getName());
        entity.setSourceid(meetid);
        entity.setSourcetype(MeetManageEntity.tableName);
        entity.setOperatedate(new Date());
        return entity;
    }

    /**
     * @param meetId
     * @param fieldName
     * @param fieldValue
     * @return
     * @description: 得到查询数目
     * @author: wanghongwei
     * @date: 2020-11-9 11:27:57
     * @modify:
     */
    private int getQueryCount(String meetId, String fieldName, int fieldValue) {
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" 1=1 ");
        sql.appendSingle(" and meetid = '{0}'", meetId);
        sql.appendSingle(" and " + fieldName + " = {0}", fieldValue);
        return this.getCount(sql.toString());
    }

    /**
     * @param dataMap
     * @param usercode
     * @description: 更新当前用户的签到状态
     * @author: wanghongwei
     * @date: 2020-12-7 16:50:33
     * @modify:
     */
    private void updateSignState(String meetid, String usercode) {
        Map<String, Object> updateMap = new HashMap<String, Object>();
        updateMap.put("signstate", MeetSignStateEnum.NoNeedSign);
        updateMap.put("signdate", "");

        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle(" 1=1 ");
        sql.appendSingle(" and meetid = {0}", meetid);
        sql.appendSingle(" and usercode = '{0}'", usercode);
        this.updateByWhere(updateMap, sql.toString());
    }

    /**
     * @param meetid
     * @param replaceusercode
     * @return
     * @description: 判断当前登录用户是否可以进行签到
     * @author: wanghongwei
     * @date: 2020-12-25 14:02:03
     * @modify: 添加重复签到校验
     */
    private boolean isCanSign(String meetid, String replaceusercode, StringBuilder errorMessage) {
        //若为替代签到则取参数 replaceusercode 当前人签到则取SessionUserBean
        String usercode = StrUtil.isEmpty(replaceusercode) ? this.getSessionUserBean().getUser().getCode() : replaceusercode;
        //重复签到校验
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("{0}  =  '{1}' ", MeetPersonRecordEntity.FieldMeetid, meetid);
        sql.appendSingle(" And {0}  =  '{1}' ", MeetPersonRecordEntity.FieldUsercode, usercode);
        sql.appendSingle(" And {0}  =  '{1}' ", MeetPersonRecordEntity.FieldSignstate, MeetSignStateEnum.Signed);
        List<MeetPersonRecordEntity> signEntites = this.queryByWhere(sql.toString());
        if (!signEntites.isEmpty()) {
            errorMessage.append(replaceusercode.contentEquals(this.getSessionUserBean().getUser().getCode()) ? "您" : "").append("已签到，无需重复签到。");
            return false;
        }
        //会议发起人 随时签到
        MeetManageEntity meetManageEntity = this.meetManageService.queryById(meetid);
        if (meetManageEntity == null) {
            errorMessage.append("会议已失效或不存在。");
            return false;
        }
        String meetSourceApp = meetManageEntity.getSourceapp() == null ? "" : meetManageEntity.getSourceapp();

        if (MPM.contentEquals(meetSourceApp) && meetManageEntity.getSignstate() == BaseSystemConst.CboYesNoEnum.No) {
            errorMessage.append("会议已停止签到，无法再进行签到操作");
            return false;
        }
        if (meetManageEntity.getUsercode().equals(this.getSessionUserBean().getUser().getCode())) {
            return true;
        }
        //判断开始签到
        LocalDateTime now = LocalDateTime.now();
        Date beginTime = meetManageEntity.getBegintime();
        if (beginTime != null) {
            LocalDateTime begintime = meetManageEntity.getBegintime().toInstant().atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
            double start = ConvertUtil.convertToDouble(ParameterCache.getValue("ForbidSignForStart", "1"));
            LocalDateTime allowSignStartTime = begintime.minusMinutes((long) (start * 60));
            if (now.isBefore(allowSignStartTime)) {
                errorMessage.append("会议开始前半小时才能签到！");
                return false;
            }
        }
        //判断结束签到
        Date endTime = meetManageEntity.getEndtime();
        if (endTime != null) {
            LocalDateTime endtime = meetManageEntity.getEndtime().toInstant().atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
            double end = ConvertUtil.convertToDouble(ParameterCache.getValue("ForbidSignForEnd", "1"));
            LocalDateTime allowSignEndTime = endtime.plusMinutes((long) (end * 60));
            if (now.isAfter(allowSignEndTime)) {
                errorMessage.append("签到时间已过，不能签到！");
                return false;
            }
        }
        return true;
    }

    /**
     * @param meetId
     * @param repalceUserCode
     * @return
     * @description: 查询人员是否已签到
     * @author xinfushuo
     * @date 2022/6/8
     * @modify
     */
    @Override
    public Boolean isAlreadySigned(String meetId, String repalceUserCode) {
        String usercode = repalceUserCode.isEmpty() ? this.getSessionUserBean().getUser().getCode() : repalceUserCode;
        StringBufferProxy sql = new StringBufferProxy();
        sql.appendSingle("{0}  =  '{1}' ", BaseOperateRecordEntity.FieldSourceid, meetId);
        sql.appendSingle(" And {0}  =  '{1}' ", BaseOperateRecordEntity.FieldSourcetype, MeetManageEntity.tableName);
        sql.appendSingle(" And {0}  =  '{1}' ", BaseOperateRecordEntity.FieldOperatetype, BaseOperateTypeEnum.Sign);
        sql.appendSingle(" And {0}  =  '{1}' ", BaseOperateRecordEntity.FieldUsercode, usercode);
        List<BaseOperateRecordEntity> signEntites = baseOperateRecordService.queryByWhere(sql.toString());
        return !signEntites.isEmpty();
    }

    /** 处理签到列显示值
     * @author: xinfushuo
     * @date: 2017年3月6日下午4:35:17
     * @params: @param mapRow
     * @description:
     * @modify:
     */
    @Override
    public void setDispFields(Map<String, Object> mapRow, DatacodeCache datacodeCache) {
        String temp;
        super.setDispFields(mapRow, datacodeCache);
        if (mapRow.get("signstate") != null) {
            temp = mapRow.get("signstate").toString();
            mapRow.put("dispneedsign", temp.contentEquals("" + MeetSignStateEnum.NoNeedSign) ? "无需签到" : "需要签到");
        }
        //邀请方式
        if (mapRow.get("invitetype") != null && mapRow.get("signstate") != null) {
            temp = mapRow.get("invitetype").toString();
            boolean signed = ConvertUtil.convertToString(mapRow.get("signstate")).contentEquals("" + MeetSignStateEnum.Signed);
            //邀请方式为发起人配置的 赋值 isConfigure为true
            temp = (MeetInviteMode.Configure.contentEquals(temp) ? BaseSystemConst.CboYesNoEnum.Yes : BaseSystemConst.CboYesNoEnum.No) + "";
            mapRow.put("isconfigure", datacodeCache.getValueDynamic("CboYesNo", temp, "code", "name"));
            //实际参会为已签到人员
            temp = (signed ? BaseSystemConst.CboYesNoEnum.Yes : BaseSystemConst.CboYesNoEnum.No) + "";
            mapRow.put("isattended", datacodeCache.getValueDynamic("CboYesNo", temp, "code", "name"));
        }
    }
}
